{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. Decentralized Optimizaiton\n",
    "\n",
    "## 2.1 Network topologies\n",
    "\n",
    "To run decentralized algorithms, we have to set up the network topology. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import scipy.io as sio\n",
    "import networkx as nx   # nx will be used for network topology creating and plotting\n",
    "from bluefog.common import topology_util\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# You can change NUM_PROC into any value smaller than the number of CPUs you have.\n",
    "import os\n",
    "NUM_PROC = 2 if os.getenv(\"TEST_ENV\") else 8\n",
    "NUM_PROC"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.1 Ring topology"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "network_size = 8\n",
    "G = topology_util.RingGraph(network_size)\n",
    "labels={i: i for i in range(network_size)}\n",
    "nx.draw_circular(G, labels=labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.2 Mesh Grid topology"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "network_size = 8\n",
    "G = topology_util.MeshGrid2DGraph(network_size)\n",
    "labels={i: i for i in range(network_size)}\n",
    "nx.draw_spring(G, labels=labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1.3 Exponential-two topology"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "network_size = 8\n",
    "G = topology_util.ExponentialTwoGraph(network_size)\n",
    "labels={i: i for i in range(network_size)}\n",
    "nx.draw_circular(G, labels=labels)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.2 Decentralized ADMM\n",
    "\n",
    "Continue on the centralized ADMM algorithm. We consider the same consensus problem:\n",
    "$$\n",
    "    \\min_{x} \\sum_{i=1}^n h_i(x)\n",
    "$$\n",
    "Instead of relaxing $x$ into $\\{x_i\\}$ and forcing them to be the common value $y$, we can map it into a graph structure. More percisely, assigning $h_i$ into each vertex and relaxing the common $x$ by $\\{x_i\\}$ owned by each vertex. The constraint of $x_i = x_j$ can be transfered into constrain on the edge:\n",
    "\n",
    "\\begin{align}\n",
    "    \\min_{\\{x_i\\}_{i\\in V},\\; \\{y_e\\}_{e\\in E} }&\\;\\; \\sum_{i=1}^n h_i(x_i)\\\\\n",
    "    {\\rm subject\\ to} &\\;\\; x_i - y_e=0,\\;  x_j - y_e=0, \\;\\;\\forall e=\\{i,j\\} \\in E\n",
    "\\end{align}\n",
    "\n",
    "As long as the graph is connected, it is easy to see it is equivalent to original consenus problem.\n",
    "\n",
    "To solve this, we consider the augmented Lagrangian and the dual variables $u_{e,i}$ for $x_i - y_e=0$ and $u_{e,j}$ for $x_j - y_e=0$. After applying the ADMM algorithm and simplifying, we obtain\n",
    "\n",
    "\\begin{align}\n",
    "    x_{i}^{k+1} =& {\\rm Prox}_{(\\alpha |N_i|)^{-1} h_i} (v_i^k)\\\\\n",
    "    a_{i}^{k+1} =& \\frac{1}{2|N_i|} \\sum_{j\\in N_i} x_j^{k+1}\\\\\n",
    "    v_{i}^{k+1} =& v_{i}^{k} + a_{i}^{k+1} - (a_{i}^{k} + x_{i}^{k})/2\n",
    "\\end{align}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The code snippet:\n",
    "```python\n",
    "bf.set_topology(topology_util.RingGraph(bf.size()))\n",
    "\n",
    "def DecentralizedADMMStepL2(A, b, x, a, v, n_i, alpha):\n",
    "    next_x = ProximalStepL2(A, b, v, n_i, alpha)\n",
    "    # `bf.in_neighbor_ranks()` loads all incoming neighbor ranks of the topology in `bf.set_topology()`\n",
    "    neighbor_weights = {r: 1.0 / n_i for r in bf.in_neighbor_ranks()}\n",
    "    next_a = bf.neighbor_allreduce(\n",
    "        next_x, self_weight=0.0, neighbor_weights=neighbor_weights\n",
    "    )   # <-- this is the key difference. Changing from allreduce to neighbor_allreduce\n",
    "    next_v = v + next_a - (x + a) / 2\n",
    "    return next_x, next_a, next_v\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "ExecuteTime": {
     "end_time": "2021-03-30T05:54:19.854663Z",
     "start_time": "2021-03-30T05:54:16.713680Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Decentralized ADMM] Allreduce residue gradient norm: 1.1404968325674104e-15\n",
      "[Decentralized ADMM] Rank 1: ADMM residue gradient norm: 1.6168195861154377e-14\n",
      "[Decentralized ADMM] Rank 0: ADMM residue gradient norm: 1.6168195861154377e-14\n",
      "[Decentralized ADMM] Rank 2: ADMM residue gradient norm: 1.6168195861154377e-14\n",
      "[Decentralized ADMM] Rank 3: ADMM residue gradient norm: 1.6168195861154377e-14\n",
      "Last three entries of x_ar:\n",
      " tensor([[0.6872],\n",
      "        [0.6552],\n",
      "        [0.8751]], dtype=torch.float64)\n",
      "Last three entries of x_admm:\n",
      " tensor([[0.6872],\n",
      "        [0.6552],\n",
      "        [0.8751]], dtype=torch.float64)\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python DecentralizedADMM.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "mse_records_dict = sio.loadmat('results/DecentralizedADMM.mat')\n",
    "\n",
    "plt.semilogy(mse_records_dict[\"mse\"][0], label=\"Decentralized ADMM\")\n",
    "plt.title(\"Decentralized ADMM\")\n",
    "plt.xlabel(\"iteration\")\n",
    "plt.ylabel(\"Mean-Square-Error\")\n",
    "plt.grid(\"on\")\n",
    "plt.legend()\n",
    "dirname = 'images'\n",
    "if not os.path.exists(dirname):\n",
    "    os.makedirs(dirname)\n",
    "plt.savefig(os.path.join(dirname, 'decentralized_admm.png'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.3 Mixing matrix\n",
    "\n",
    "For commonly used undirected network, BlueFog provides the mixing matrix generated through the Metropolis–Hastings rule. \n",
    "\n",
    "> **Metropolis-Hastings rule.** Providing a undirected and connected topology $\\mathcal{G}$, we select $w_{ij}$ as\n",
    "> \n",
    ">\\begin{align}\n",
    "\\hspace{-3mm}\tw_{ij}=\n",
    "\t\\begin{cases}\n",
    "\t\t\\begin{array}{ll}\\displaystyle\n",
    "\t\t\t\\hspace{-2mm}\\frac{1}{1 + \\max\\{d_i, d_j \\}},& \\mbox{if $j \\in \\mathcal{N}(i)$}, \\\\\n",
    "\t\t\t\\hspace{-2mm}\\displaystyle 1 - \\sum_{j\\in \\mathcal{N}(i)}w_{ij}, & \\mbox{if $i = j$},\\\\\n",
    "\t\t\t\\hspace{-2mm}0,& \\mbox{if $j \\notin \\mathcal{N}(i)$  and $j\\neq i$}.\n",
    "\t\t\\end{array}\n",
    "\t\\end{cases}\n",
    "\\end{align}\n",
    ">\n",
    "> where $d_i = |\\mathcal{N}(i)|$ (the number of incoming neighbors of agent $k$). It is easy to verify such $W$ is always doubly-stochastic."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.1 Mixing matrix for the ring\n",
    "\n",
    "The following code is to fetch mixing matrix provided by BlueFog.\n",
    "\n",
    "```python\n",
    "def FetchRingMixingMatrix(network_size):\n",
    "    G = topology_util.RingGraph(network_size)   # organize nodes into a ring\n",
    "    W = np.zeros((network_size, network_size))  # genearate an empty mixing matrix \n",
    "\n",
    "    for rank in range(network_size):\n",
    "        self_weight, neighbor_weights = topology_util.GetRecvWeights(G, rank)  # fetch weights\n",
    "        W[rank,rank] = self_weight              # put weights into the mixing matrix\n",
    "        for r, v in neighbor_weights.items():\n",
    "            W[rank, r] = v\n",
    "            \n",
    "    return W\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.333 0.333 0.    0.    0.    0.    0.    0.333]\r\n",
      " [0.333 0.333 0.333 0.    0.    0.    0.    0.   ]\r\n",
      " [0.    0.333 0.333 0.333 0.    0.    0.    0.   ]\r\n",
      " [0.    0.    0.333 0.333 0.333 0.    0.    0.   ]\r\n",
      " [0.    0.    0.    0.333 0.333 0.333 0.    0.   ]\r\n",
      " [0.    0.    0.    0.    0.333 0.333 0.333 0.   ]\r\n",
      " [0.    0.    0.    0.    0.    0.333 0.333 0.333]\r\n",
      " [0.333 0.    0.    0.    0.    0.    0.333 0.333]]\r\n",
      "\r\n",
      "The sum of each col is: [1. 1. 1. 1. 1. 1. 1. 1.]\r\n",
      "The sum of each row is: [1. 1. 1. 1. 1. 1. 1. 1.]\r\n",
      "W is doubly stochastic.\r\n",
      "The second largest eigenvalue is: 0.804737854124365\r\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python Ring_mixingMatrix.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.2 Mixing matrix for the Mesh"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.417 0.25  0.    0.    0.333 0.    0.    0.   ]\r\n",
      " [0.25  0.25  0.25  0.    0.    0.25  0.    0.   ]\r\n",
      " [0.    0.25  0.25  0.25  0.    0.    0.25  0.   ]\r\n",
      " [0.    0.    0.25  0.417 0.    0.    0.    0.333]\r\n",
      " [0.333 0.    0.    0.    0.417 0.25  0.    0.   ]\r\n",
      " [0.    0.25  0.    0.    0.25  0.25  0.25  0.   ]\r\n",
      " [0.    0.    0.25  0.    0.    0.25  0.25  0.25 ]\r\n",
      " [0.    0.    0.    0.333 0.    0.    0.25  0.417]]\r\n",
      "\r\n",
      "The sum of each col is: [1. 1. 1. 1. 1. 1. 1. 1.]\r\n",
      "The sum of each row is: [1. 1. 1. 1. 1. 1. 1. 1.]\r\n",
      "W is doubly stochastic.\r\n",
      "The second largest eigenvalue is: 0.8535533905932756\r\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python Mesh_mixingMatrix.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.3 Mixing matrix for Exponential-two Graph"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In the exponential-two graph, each node has the same incoming degree and outgoing degree. Exponential-two graph is a directed graph, BlueFog provides a mixing matrix following averaging rule for Exponential-two graph.\n",
    "\n",
    "> **Averaging rule.** Providing an exponential-two topology $\\mathcal{G}$, we select $w_{ij}$ as\n",
    "> \n",
    ">\\begin{align}\n",
    "\\hspace{-3mm}\tw_{ij}=\n",
    "\t\\begin{cases}\n",
    "\t\t\\begin{array}{ll}\\displaystyle\n",
    "\t\t\t\\hspace{-2mm}\\frac{1}{1 + d},& \\mbox{if $j \\in \\mathcal{N}_{\\rm in}(i)$ or if $i = j$} , \\\\\n",
    "\t\t\t0,& \\mbox{otherwise}.\n",
    "\t\t\\end{array}\n",
    "\t\\end{cases}\n",
    "\\end{align}\n",
    ">\n",
    "> where $d = |\\mathcal{N}_{\\rm in}(i)|$ (the number of incoming neighbors of agent $i$). It is easy to verify such $W$ is always doubly-stochastic because incoming degree $d$ of each node is the same.\n",
    "\n",
    "Since Exponential-two Graph is a regular graph, such mixing matrix is doubly stochastic but not symmetric."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0.25 0.   0.   0.   0.25 0.   0.25 0.25]\r\n",
      " [0.25 0.25 0.   0.   0.   0.25 0.   0.25]\r\n",
      " [0.25 0.25 0.25 0.   0.   0.   0.25 0.  ]\r\n",
      " [0.   0.25 0.25 0.25 0.   0.   0.   0.25]\r\n",
      " [0.25 0.   0.25 0.25 0.25 0.   0.   0.  ]\r\n",
      " [0.   0.25 0.   0.25 0.25 0.25 0.   0.  ]\r\n",
      " [0.   0.   0.25 0.   0.25 0.25 0.25 0.  ]\r\n",
      " [0.   0.   0.   0.25 0.   0.25 0.25 0.25]]\r\n",
      "\r\n",
      "The sum of each col is: [1. 1. 1. 1. 1. 1. 1. 1.]\r\n",
      "The sum of each row is: [1. 1. 1. 1. 1. 1. 1. 1.]\r\n",
      "W is doubly stochastic.\r\n",
      "The second largest eigenvalue is: 0.5000000000000003\r\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python Exp2_mixingMatrix.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.3.4 Commonly-used topology summary\n",
    "\n",
    "The following table summarizes the second largest eigenvalue and the maximum degree of some common network topologes. The mixing matrix of the undirected topologies, i.e., the ring, 2D-mesh, and fully-connected topology, are generated through the Matropolis-Hastings  rule, while the mixing matrix of exponential-2 topology (which is a directed network) is genereted through the Averaging rule. \n",
    "\n",
    "\n",
    "| Network topology | second largest eigenvalue | maximum degree |\n",
    "| -: | :-: | :-: |\n",
    "| Undirected Ring | $1-O(\\frac{1}{n^2})$ | 2 |\n",
    "| Undirected 2D-Mesh | $1-O(\\frac{1}{n})$ | 4 |\n",
    "| Exponential-2 | $1-O(\\frac{1}{\\ln(n)})$ | $\\ln(n)$ |\n",
    "| Fully connected| $0$ |$n-1$ |  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.4 Average consensus\n",
    "\n",
    "Given the mixing matrix, the average consensus algorithm is:\n",
    "\n",
    "$$x_i^{k+1} = \\sum_{j \\in \\mathcal{N}_i \\cup \\{i\\}} w_{ij} x_j^{k}$$\n",
    "\n",
    "It is guaranteed that $ \\frac{1}{n}\\sum_{i=1}^n \\|x_i^k - \\frac{1}{n}\\sum_{i=1}^n x_i^0\\|^2 \\le C \\rho^{2k}$, where $\\rho$ is the second largest eigenvalue of the matrix $W$. Apparently, $\\rho$ decides the convergence rate of the average consensus algorithm. One step of average consensus can be conducted as\n",
    "\n",
    "```python\n",
    "G = topology_util.RingGraph(bf.size())  # set up the topology\n",
    "bf.set_topology(G, is_weighted=True)    # organize nodes into the topology\n",
    "# one-step average consensus\n",
    "def avg_consensus_one_step(x):\n",
    "    x_next = bf.neighbor_allreduce(x)\n",
    "    return x_next\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Runing average consensus with topology Ring\n",
      "Progress 0/60\n",
      "Progress 10/60\n",
      "Progress 20/60\n",
      "Progress 30/60\n",
      "Progress 40/60\n",
      "Progress 50/60\n",
      "Runing average consensus with topology Mesh\n",
      "Progress 0/60\n",
      "Progress 10/60\n",
      "Progress 20/60\n",
      "Progress 30/60\n",
      "Progress 40/60\n",
      "Progress 50/60\n",
      "Runing average consensus with topology Exp2\n",
      "Progress 0/60\n",
      "Progress 10/60\n",
      "Progress 20/60\n",
      "Progress 30/60\n",
      "Progress 40/60\n",
      "Progress 50/60\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python AverageConsensus.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rel_error_dict = sio.loadmat('results/AverageConsensus.mat')\n",
    "for graph in ['Ring', 'Mesh', 'Exp2']:\n",
    "    record = rel_error_dict[graph].reshape(-1)\n",
    "    plt.semilogy(record)\n",
    "plt.legend(['Ring', 'Mesh', 'Exp2'], fontsize=16)\n",
    "plt.xlabel('Iteration', fontsize=16)\n",
    "plt.ylabel('Relative error', fontsize=16)\n",
    "dirname = 'images'\n",
    "if not os.path.exists(dirname):\n",
    "    os.makedirs(dirname)\n",
    "plt.savefig(os.path.join(dirname, 'AverageConsensus.png'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The above figure depicts the influence of $\\rho$. "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.5 Decentralized gradient descent\n",
    "\n",
    "Recall the optimization problem:\n",
    "\n",
    "\\begin{align*}\n",
    "\\min_{x\\in \\mathbb{R}^d}\\ \\sum_{i=1}^n h_i(x)\\hspace{1cm}  \\mbox{(Opt-Problem)}\n",
    "\\end{align*}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Decentralized gradient descent has two fomulations: \n",
    "\n",
    "\\begin{align}\n",
    "x_i^{(k+1)} &= \\sum_{j\\in \\mathcal{N}_i \\cup \\{i\\}} w_{ij} \\Big(x_j^{(k)} - \\alpha \\nabla h_j(x_j^{(k)}) \\Big)  \\hspace{2.1cm} \\mbox{(adaptation-then-combination, ATC-DGD)}\\\\ \n",
    "x_i^{(k+1)} &= \\sum_{j\\in \\mathcal{N}_i \\cup \\{i\\}} w_{ij} x_j^{(k)} - \\alpha \\nabla h_i(x_i^{(k)})   \\hspace{2.6cm} \\mbox{(adaptation-with-combination, AWC-DGD)}\n",
    "\\end{align}\n",
    "\n",
    "The comparison between ATC and AWC DGD is as follows:\n",
    "\n",
    "- ATC-DGD has smaller limiting bias than AWC-DGD\n",
    "\n",
    "\n",
    "- ATC-DGD has a wider step-size stability range than AWC-DGD\n",
    "\n",
    "\n",
    "- AWC-DGD can easily overlap communication and computation, and hence is more efficient per iteration than ATC-DGD\n",
    "\n",
    "\n",
    "### 2.5.1 Compare limiting bias\n",
    "\n",
    "In the following example, we will consider the simple scenario in which $h_i(x) = \\frac{1}{2}\\|A_i x - b_i\\|^2$. The main code is as follows:\n",
    "\n",
    "```Python\n",
    "G = topology_util.RingGraph(bf.size())  # set up the topology\n",
    "bf.set_topology(G, is_weighted=True)    # organize nodes into the topology\n",
    "\n",
    "# one-step AWC-DGD. \n",
    "def AWC_DGD_one_step(x, x_opt, A, b, alpha=1e-2):\n",
    "\n",
    "    grad_local = A.t().mm(A.mm(x) - b)                       # compute local grad\n",
    "    x_next = bf.neighbor_allreduce(x) - alpha*grad_local     # AWC update\n",
    "\n",
    "    return x_next\n",
    "\n",
    "# one-step ATC-DGD. \n",
    "def ATC_DGD_one_step(x, x_opt, A, b, alpha=1e-2):\n",
    "\n",
    "    grad_local = A.t().mm(A.mm(x) - b)      # compute local grad\n",
    "    y = x - alpha*grad_local                # adapte\n",
    "    x_new = bf.neighbor_allreduce(y)        # combination\n",
    "\n",
    "    return x_next\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Distributed Grad Descent] Rank 0: global gradient norm: 3.7252473072675936e-13\n",
      "\n",
      "Running ATC:\n",
      "Progress 0/200\n",
      "Progress 100/200\n",
      "\n",
      "Running AWC:\n",
      "Progress 0/200\n",
      "Progress 100/200\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python DGD_limitBias.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rel_error_dict = sio.loadmat('results/DGD_limitBias.mat')\n",
    "\n",
    "for method in ['ATC', 'AWC']:\n",
    "    record = rel_error_dict[method].reshape(-1)\n",
    "    plt.semilogy(record)\n",
    "    \n",
    "plt.legend(['ATC', 'AWC'], fontsize=16)\n",
    "plt.xlabel('Iteration', fontsize=16)\n",
    "plt.ylabel('Relative error', fontsize=16)\n",
    "plt.title('step-size: 5e-3')\n",
    "\n",
    "dirname = 'images'\n",
    "if not os.path.exists(dirname):\n",
    "    os.makedirs(dirname)\n",
    "plt.savefig(os.path.join(dirname, 'DGD_limitBias.png'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is observed in the above figure that with the same step-size, ATC can converge to a better solution than AWC."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.5.2 Compare stability range"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Distributed Grad Descent] Rank 0: global gradient norm: 3.7252473072675936e-13\n",
      "\n",
      "Running ATC:\n",
      "Progress 0/200\n",
      "Progress 100/200\n",
      "\n",
      "Running AWC:\n",
      "Progress 0/200\n",
      "Progress 100/200\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python DGD_stability.py"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rel_error_dict = sio.loadmat('results/DGD_stability.mat')\n",
    "\n",
    "for method in ['ATC', 'AWC']:\n",
    "    record = rel_error_dict[method].reshape(-1)\n",
    "    plt.semilogy(record)\n",
    "    \n",
    "plt.legend(['ATC', 'AWC'], fontsize=16)\n",
    "plt.xlabel('Iteration', fontsize=16)\n",
    "plt.ylabel('Relative error', fontsize=16)\n",
    "plt.title('step-size: 5e-2')\n",
    "\n",
    "dirname = 'images'\n",
    "if not os.path.exists(dirname):\n",
    "    os.makedirs(dirname)\n",
    "plt.savefig(os.path.join(dirname, 'DGD_stability.png'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When we enlarge the step-size, it is observed that AWC diverges while ATC can still converge"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.5.3 Compare communication and computation overlapping\n",
    "\n",
    "Computation is mainly executed in the CPUs or GPUs, while communication depends on the network situation, other machine's or core's response, etc.\n",
    "In other words, they are using complete different resources, which is perfect for overlapping. If it is doing properly, it can save use lots of time.\n",
    "Adapt-With-Combination is one typical example that can overlap the communication and computation naturally.\n",
    "\n",
    "To achieve than you need to call the nonblocking version functions, for example:\n",
    "\n",
    "``` python\n",
    "def AWC_DGD_one_step(x, x_opt, A, b, alpha=1e-2):\n",
    "    grad_local = A.t().mm(A.mm(x) - b)                       # compute local grad\n",
    "    x_new = bf.neighbor_allreduce(x) - alpha*grad_local      # AWC update\n",
    "\n",
    "def NonBlocking_AWC_DGD_one_step(x, x_opt, A, b, alpha=1e-2):\n",
    "    x_handle = bf.neighbor_allreduce_nonblocking(x)          # Nonblocking function returns handle instead of tensor.\n",
    "    grad_local = A.t().mm(A.mm(x) - b)                       # compute local grad\n",
    "    x_new = bf.wait(x_handle) - alpha*grad_local             # AWC update. Note calling `wait` on the handle.\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "Running ATC:\n",
      "Progress 0/1000\n",
      "Progress 200/1000\n",
      "Progress 400/1000\n",
      "Progress 600/1000\n",
      "Progress 800/1000\n",
      "ATC finishes in 3.258173704147339 seconds.\n",
      "\n",
      "Running AWC:\n",
      "Progress 0/1000\n",
      "Progress 200/1000\n",
      "Progress 400/1000\n",
      "Progress 600/1000\n",
      "Progress 800/1000\n",
      "AWC finishes in 3.0531022548675537 seconds.\n",
      "\n",
      "Running NBK-AWC:\n",
      "Progress 0/1000\n",
      "Progress 200/1000\n",
      "Progress 400/1000\n",
      "Progress 600/1000\n",
      "Progress 800/1000\n",
      "NBK-AWC finishes in 1.9056735038757324 seconds.\n"
     ]
    }
   ],
   "source": [
    "! bfrun -np $NUM_PROC python NonBlocking.py"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "It is observed that Nonblocking-AWC has the shortest time to finish $1000$ iterations through overlapping of communication and computation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "rel_error_dict = sio.loadmat('results/NonBlocking.mat')\n",
    "for method in ['ATC', 'AWC', 'NBK-AWC']:\n",
    "    record = rel_error_dict[method].reshape(-1)\n",
    "    time = rel_error_dict[method+\"_time\"].reshape(-1)\n",
    "    plt.semilogy(time, record)\n",
    "    \n",
    "plt.legend(['ATC', 'AWC', 'NBK-AWC'], fontsize=16)\n",
    "plt.xlabel('Time', fontsize=16)\n",
    "plt.ylabel('Relative error', fontsize=16)\n",
    "plt.title('Running time comparison')\n",
    "\n",
    "dirname = 'images'\n",
    "if not os.path.exists(dirname):\n",
    "    os.makedirs(dirname)\n",
    "plt.savefig(os.path.join(dirname, 'NonBlockingTime.png'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}